package nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * @author zhangxin
 * @date 2020/10/10
 */
public class MyServer {

    private int size = 1024;

    private ServerSocketChannel serverSocketChannel;

    private ByteBuffer buffer;

    private Selector selector;

    private int remoteClientNum = 0;


    public MyServer(int port) {
        try {
            //
            initChannel(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initChannel(int port) throws IOException {
        serverSocketChannel = ServerSocketChannel.open();
        //    设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //    绑定端口
        serverSocketChannel.bind(new InetSocketAddress(port));
        // selector
        selector = Selector.open();

        // 注册通道
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 分配缓冲区大小
        buffer = ByteBuffer.allocate(size);

    }

    private void listener() throws IOException {
        while (true) {
            // 返回int表示有多少个channel处于就绪状态
            int select = selector.select();

            if (select == 0) {
                continue;
            }

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();

                // 如果处于连接就绪状态，则开始接收客户端的连接
                if (selectionKey.isAcceptable()) {
                    // 获取Channel
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                    // Channel接收连接
                    SocketChannel channel = serverSocketChannel.accept();

                    // 注册channel
                    registerChannel(selector, channel, SelectionKey.OP_READ);

                    remoteClientNum++;

                    System.out.println("online client num" + remoteClientNum);
                }

                //    如果处于读就绪
                if (selectionKey.isReadable()) {
                    read(selectionKey);
                }
                iterator.remove();
            }
        }

    }

    private void read(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        int count;

        buffer.clear();

        // 从通道中读数据到缓冲区
        while ((count = channel.read(buffer)) > 0) {

            // byteBuffer写模式变读模式
            buffer.flip();

            while (buffer.hasRemaining()) {
                System.out.println((char) buffer.get());
            }

        }


    }

    private void registerChannel(Selector selector, SocketChannel channel, int opRead) throws IOException {
        if (channel == null) {
            return;
        }

        channel.configureBlocking(false);
        channel.register(selector, opRead);
    }

    public static void main(String[] args) {
        try {
            MyServer myServer = new MyServer(9999);
            myServer.listener();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

